package com.naiterui.ehp.bs.b2c.order.service.impl.logistics;

import cn.hutool.core.collection.CollectionUtil;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import com.google.common.collect.Maps;
import com.naiterui.ehp.bp.support.exception.JsonException;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.bp.utils.net.RestHttpUtil;
import com.naiterui.ehp.bs.b2c.order.bo.LogisticsInfoBO;
import com.naiterui.ehp.bs.b2c.order.bo.LogisticsTraceLogBO;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.BaseResponse;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.zto.request.ZtoTraceQueryRequest;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.zto.response.ZtoTrace;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.zto.response.ZtoTraceLogs;
import com.naiterui.ehp.bs.b2c.order.vo.logistics.zto.response.ZtoTraceQueryResponse;

import lombok.extern.slf4j.Slf4j;

/**
 * 中通快递
 */
@Slf4j
@Service("zhongtong")
public class ZtoLogisticsTraceServiceImpl extends AbstractLogisticsTraceService<ZtoTraceQueryRequest> {

    private final String companyId = "e06acc95e4b449b58021d57c49cea8d9";

    private final String companyKey = "e8fa246b92f3";

    @Override
    public Map<String, LogisticsInfoBO> getTrace(List<String> deliveryIds) {
        Map<String, LogisticsInfoBO> logisticsTraceInfoMap = Maps.newHashMap();
        ZtoTraceQueryRequest ztoTraceQueryRequest = new ZtoTraceQueryRequest();
        ztoTraceQueryRequest.setDeliveryIds(deliveryIds);
        try {
            ZtoTraceQueryResponse traceQueryResponse = this.execute(ztoTraceQueryRequest, new ParameterizedTypeReference<ZtoTraceQueryResponse>() {
            });
            Map<String, List<ZtoTrace>> collectMap = traceQueryResponse.getData()
                                                                       .stream()
                                                                       .collect(Collectors.toMap(ZtoTraceLogs::getBillCode, ZtoTraceLogs::getTraces));
            collectMap.forEach((deliveryId, value) -> {
                LogisticsInfoBO logisticsInfo = new LogisticsInfoBO();
                logisticsInfo.setDeliveryId(deliveryId);
                List<LogisticsTraceLogBO> traceLogs = value.stream()
                                                           .map(ztoTrace -> LogisticsTraceLogBO.builder()
                                                                                               .content(ztoTrace.getDesc())
                                                                                               .address(ztoTrace.getScanSite())
                                                                                               .time(ztoTrace.getScanDate())
                                                                                               .build())
                                                           .collect(Collectors.toList());
                logisticsInfo.setTraceLogs(traceLogs);
                if (CollectionUtil.isEmpty(traceLogs)) {
                    logisticsInfo.setStatus(LogisticsInfoBO.STATUS_NONE);
                } else {
                    //找到物流状态
                    List<String> collect = value.stream().map(ZtoTrace::getScanType).collect(Collectors.toList());
                    if (collect.contains("签收") || collect.contains("第三方签收") || collect.contains("ARRIVAL") || collect.contains("SIGNED")) {
                        logisticsInfo.setStatus(LogisticsInfoBO.STATUS_RECEIVED);
                    } else if (collect.contains("收件")) {
                        logisticsInfo.setStatus(LogisticsInfoBO.STATUS_PICKUP);
                    } else if (collect.contains("退件签收")) {
                        logisticsInfo.setStatus(LogisticsInfoBO.STATUS_REJECT);
                    } else {
                        logisticsInfo.setStatus(LogisticsInfoBO.STATUS_ONWAY);
                    }
                }
                logisticsTraceInfoMap.put(deliveryId, logisticsInfo);
            });
        } catch (JsonException e) {
            log.error("json转换失败", e);
        }
        return logisticsTraceInfoMap;
    }

    @Override
    protected <E extends BaseResponse> E execute(ZtoTraceQueryRequest ztoTraceQueryRequest,
                                                 ParameterizedTypeReference<E> responseTypeReference) {
        String serviceUrl = ztoTraceQueryRequest.getServiceUrl();
        Map<String, String> paramMap = Maps.newHashMap();
        paramMap.put("data", JsonMapper.toJson(ztoTraceQueryRequest.getDeliveryIds()));
        paramMap.put("msg_type", "NEW_TRACES");
        paramMap.put("company_id", this.companyId);

        String strToDigestBuilder = paramMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue() + "&").collect(Collectors.joining());

        Map<String, String> header = Maps.newHashMap();
        header.put("x-companyid", this.companyId);
        String datadigest = Base64.encodeBase64String(
                DigestUtils.md5(strToDigestBuilder.substring(0, strToDigestBuilder.length() - 1) + this.companyKey));
        header.put("x-datadigest", datadigest);
        ResponseEntity<String> responseEntity = RestHttpUtil.post()
                                                            .url(serviceUrl)
                                                            .header(header)
                                                            .paramMap(paramMap)
                                                            .execute(new ParameterizedTypeReference<String>() {
                                                            });

        return JsonMapper.toObject(responseEntity.getBody(), responseTypeReference);
    }

}
